﻿/**
 * Vector2P
 * 
 * @author		Allen Chou
 * @version		1.0.4 (last update: Nov 16 2008)
 * @link        http://cjcat.blogspot.com
 * @link		http://cjcat2266.deviantart.com
 */

package idv.cjcat.geom {
	import flash.display.*;
	import flash.errors.*;
	
	import idv.cjcat.*;
	import idv.cjcat.geom.Vector2;

	public class Vector2P extends Vector2 {
		
		private var _theta:Number;
		private var _rFactor:Number = 1;
		
		/**
		 * @param	object
		 * @return  A <code>Vector2P</code> object representing the coordinate of <code>object</code>.
		 */
		public static function posVec(object:DisplayObject):Vector2P {
			return (new Vector2(object.x, object.y)).toVector2P();
		}
		
		/**
		 * Sets the absolute position of a <code>DisplayObject</code>.
		 * @param	object   The <code>DisplayObject</code>.
		 * @param	vector   The <code>Vector2P</code> object representing the position to be set.
		 */
		public static function setPos(object:DisplayObject, vector:Vector2P, centerX:Number = 0, centerY:Number = 0):void {
			object.x = vector.x + centerX;
			object.y = vector.y + centerY;
		}
		
		/**
		 * Sets the relative position of a <code>DisplayObject</code>.
		 * @param	object   The <code>DisplayObject</code>.
		 * @param	vector   The <code>Vector2P</code> object representing the position to be set.
		 */
		public static function stepPos(object:DisplayObject, vector:Vector2P, offsetX:Number = 0, offsetY:Number = 0):void {
			object.x += vector.x + offsetX;
			object.y += vector.y + offsetY;
		}
		
		/**
		 * Sums up <code>Vector2P</code> objects.
		 * @param	...vectors  The vectors.
		 * @return  The sum.
		 */
		public static function sum(...vectors):Vector2P {
			var tempX:Number = 0;
			var tempY:Number = 0;
			
			for (var i:int = 0; i < vectors.length; i++) {
				tempX += Vector2(vectors[i]).x;
				tempY += Vector2(vectors[i]).y;
			}
			
			return (new Vector2(tempX, tempY)).toVector2P();
		}
		
		/**
		 * Returns the difference of a vector from another.
		 * @param	from  The source vector.
		 * @param	to    The target vector.
		 * @return The difference.
		 */
		public static function relative(from:Vector2P, to:Vector2P):Vector2P {
			return (new Vector2(to.x - from.x, to.y - from.y)).toVector2P();
		}
		
		public function Vector2P(r:Number = 1, theta:Number = 0, radian:Boolean = true) {
			if (!radian) theta = theta * Math.PI / 180;
			if (r < 0) _rFactor = -1;
			super(r * Math.cos(theta), r * Math.sin(theta));
			this.theta = theta;
		}
		
		/**
		 * The radius of the polar vector.
		 */
		public function get r():Number { return _rFactor * CJMath.setPrecision(length, 10); }
		public function set r(value:Number):void {
			if (value >= 0) {
				_rFactor = 1;
			} else {
				_rFactor = -1;
			}
			length = value;
		}
		
		/**
		 * The angle of the polar vector.
		 */
		public function get theta():Number { return _theta; 	}
		public function set theta(value:Number):void {
			_theta = value;
			var temp:Number = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
			_x = _rFactor * temp * Math.cos(_theta);
			_y = _rFactor * temp * Math.sin(_theta);
			
			length = CJMath.setPrecision(length, 10);
			
			_theta =  Math.atan2(y, x);
			if (_rFactor == -1) {
				if (_theta > Math.PI && _theta < 2 * Math.PI) {
					_theta -= Math.PI;
				} else if (_theta < Math.PI) {
					_theta += Math.PI;
				} else if (_theta == Math.PI) {
					_theta = 0;
				} else if (_theta == 2 * Math.PI) {
					_theta = Math.PI;
				}
			}
		}
		
		/**
		 * Returns the result of a vector after rotated by a specified angle.
		 * @param	angle      The angle of rotation.
		 * @param	radian     Whether the unit of angle is radian; otherwise, it's in degree.
		 * @param	clockwise  Whether the rotation is clockwise; otherwise, it's counterclockwise.
		 * @return The rotated vector.
		 */
		public function rotateP(angle:Number, useAngle:Boolean = false, clockwise:Boolean = false):Vector2P {
			if (useAngle) angle = angle * Math.PI / 180;
			var factor:Number = (clockwise)?( -1):(1);
			return new Vector2P(r, theta - factor * angle);
		}
		
		/**
		 * The x value of the vector.
		 */
		override public function get x():Number { return _x; }
		override public function set x(value:Number):void {
			_x = value;
			_rFactor = 1;
		}
		
		/**
		 * The y value of the vector.
		 */
		override public function get y():Number { return _y; }
		override public function set y(value:Number):void {
			_y = value;
			_rFactor = 1;
		}
		
		/**
		 * Returns a 2D Cartesian vector equivalent of a vector.
		 * @return The polar vector.
		 */
		public function toVector2():Vector2 {
			return new Vector2(x, y);
		}
		
		/**
		 * Returns a string representation of a vector.
		 * @return The string.
		 */
		override public function toString():String {
			return "(r = " + r + ", theta = " + theta + ")";
		}
		
	}

}